﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../VTG.h"
#include "Commons.h"

namespace GnssLogs
{
namespace VTGDecoder
{
using namespace tao::pegtl;
using LogHeader = NMEA_TALKER_IDENTIFIER("VTG");
// clang-format off
struct TrackTrue : Floating {};
struct TrackTrueIndicator : one<'T'> {};
struct TrackMag : Floating {};
struct TrackMagIndicator : one<'M'> {};
struct SpeedKn : Floating {};
struct NauticalSpeedIndicator : one<'N'> {};
struct SpeedKm : Floating {};
struct SpeedIndicator : one<'K'> {};
// clang-format on
using Expression = seq<LogHeader,
                       Split,
                       TrackTrue,
                       Split,
                       TrackTrueIndicator,
                       Split,
                       opt<TrackMag>,
                       Split,
                       TrackMagIndicator,
                       Split,
                       SpeedKn,
                       Split,
                       NauticalSpeedIndicator,
                       Split,
                       SpeedKm,
                       Split,
                       SpeedIndicator,
                       Split,
                       PositioningSystemModeIndicator,
                       one<'*'>,
                       CheckSum,
                       Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<LogHeader>
{
    template<typename ParseInput>
    static bool apply(ParseInput& in, VTG::Data& data)
    {
        data.header = std::string(in.begin(), in.size());
        return true;
    }
};

template<>
struct Action<TrackTrue> : DoubleHelper<Action<TrackTrue>>
{
    static void setValue(VTG::Data& data, double value) { data.trackTrue = value; }
};

template<>
struct Action<TrackTrueIndicator>
{
    template<typename ParseInput>
    static bool apply(ParseInput& in, VTG::Data& data)
    {
        data.trackTrueIndicator = std::string(in.begin(), in.size());
        return true;
    }
};

template<>
struct Action<TrackMag> : DoubleHelper<Action<TrackMag>>
{
    static void setValue(VTG::Data& data, double value) { data.trackMag = value; }
};

template<>
struct Action<TrackMagIndicator>
{
    template<typename ParseInput>
    static bool apply(ParseInput& in, VTG::Data& data)
    {
        data.trackMagIndicator = std::string(in.begin(), in.size());
        return true;
    }
};

template<>
struct Action<SpeedKn> : DoubleHelper<Action<SpeedKn>>
{
    static void setValue(VTG::Data& data, double value) { data.speedKn = value; }
};

template<>
struct Action<NauticalSpeedIndicator>
{
    template<typename ParseInput>
    static bool apply(ParseInput& in, VTG::Data& data)
    {
        data.nauticalSpeedIndicator = std::string(in.begin(), in.size());
        return true;
    }
};

template<>
struct Action<SpeedKm> : DoubleHelper<Action<SpeedKm>>
{
    static void setValue(VTG::Data& data, double value) { data.speedKm = value; }
};

template<>
struct Action<SpeedIndicator>
{
    template<typename ParseInput>
    static bool apply(ParseInput& in, VTG::Data& data)
    {
        data.speedIndicator = std::string(in.begin(), in.size());
        return true;
    }
};

template<>
struct Action<PositioningSystemModeIndicator> : PositioningSystemModeIndicatorHelper<Action<PositioningSystemModeIndicator>>
{
    static void setValue(VTG::Data& data, PositioningSystemMode mode) { data.mode = mode; }
};

template<>
struct Action<CheckSum> : CheckSumHelper<Action<CheckSum>>
{
    static void setValue(VTG::Data& data, uint8_t value) { data.checkSum = value; }
};
} // namespace VTGDecoder
} // namespace GnssLogs